/*
 * File:    MimeTypes.java
 * Created: 15-Jul-2007
 * Version: $Id$
 *
 * COPYRIGHT (C) 2007, Bitgate Software, LLC.  All Rights Reserved.
 *
 * software@bitgatesoftware.com
 */

package com.bitgate.util.mime;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;

import com.bitgate.util.config.Config;
import com.bitgate.util.file.FileUtil;

import static com.bitgate.util.debug.Debug.*;

/**
 * This class is used to define the mime types for specific files handled by or distributed to the system.  It contains
 * the ability to retrieve mime types by the filename specified, and the ability to reload the mime types file if
 * required.
 * 
 * @author kenji
 */
public class MimeTypes
{
	private final HashMap<String, String> mimeExtensions;
	private final static MimeTypes _default = new MimeTypes();
	private final String unknownMimeType;
	
	private MimeTypes()
	{
		mimeExtensions = new HashMap<String, String>();
		
		String servicesFilename = System.getProperty("mime.config");
		
		if (servicesFilename == null) {
			servicesFilename = "conf/defaults/mime.xml";
		}
		
		Config.getDefault().register(servicesFilename, "mime");
		
		unknownMimeType = Config.getDefault().parseConfig("mime", "/mime/object[@type='tuning']/property[@name='mime.unknown']/" +
			"@value");
		
		loadMimeTypes();
	}
	
	private void loadMimeTypes()
	{
		String mimeFilename = Config.getDefault().parseConfig("mime", "/mime/object[@type='tuning']/property[@name='mime.filename']/" +
			"@value");
		BufferedReader br = null;
		
		if (mimeFilename == null) {
			throw new RuntimeException("Unable to load configuration from mime configuration: Possibly could not load mime config " +
					"from classpath.");
		}
		
		try {
			br = new BufferedReader(new InputStreamReader(FileUtil.getStream(mimeFilename)));
		} catch(IOException e) {
			critical("Unable to load mime filename '" + mimeFilename + "': " + e.getMessage());
			return;
		} catch(NullPointerException e) {
			critical("Unable to load mime filename '" + mimeFilename + "': " + e.getMessage());
			return;
		} catch(IllegalArgumentException e) {
			critical("Unable to load mime filename '" + mimeFilename + "': " + e.getMessage());
			return;
		}
		
		String line = null;
		
		while(true) {
			try {
				line = br.readLine();
			} catch(IOException e) {
				break;
			}
			
			// Indicates end of line.
			if (line == null) {
				break;
			}
			
			String mimeEntries[] = line.split("\\s");
			
			if (mimeEntries[0].startsWith("#") || mimeEntries.length == 1) {
				continue;
			}
			
			String mimeType = mimeEntries[0];
			
			for(int i = 1; i < mimeEntries.length; i++) {
				if (mimeEntries[i].length() > 0) {
					mimeExtensions.put(mimeEntries[i].toLowerCase(), mimeType);
				} else {
					continue;
				}
				
				if (isDebugEnabled()) {
					debug("Mime: Extension='" + mimeEntries[i].toLowerCase() + "' Value='" + mimeType + "'");
				}
			}
		}
		
		try {
			br.close();
		} catch(IOException e) {
			if (isDebugEnabled()) {
				debug("Unable to close mime filename '" + mimeFilename + "': " + e.getMessage());
			}
		}
	}
	
	public static MimeTypes getDefault()
	{
		return _default;
	}
	
	public String get(String extension)
	{
		if (extension == null) {
			return unknownMimeType;
		}
		
		String mimeExt = mimeExtensions.get(extension.toLowerCase());
		
		if (mimeExt == null) {
			return unknownMimeType;
		}
		
		return mimeExt;
	}
	
	public void reload()
	{
		mimeExtensions.clear();
		loadMimeTypes();
	}
}